import { KeywordNode, Program } from '@shaderfrog/glsl-parser/ast';
import { IShaderLayoutInfo } from '../IShaderLayoutInfo';

/**
 * 获取 activeUniforms 。
 *
 * @param program 语法树。
 */
export function activeUniforms(program: Program, options: IShaderLayoutInfo)
{
    for (let i = 0; i < program.program.length; i++)
    {
        // 遍历程序查找 unifrom
        const element = program.program[i];
        if (element.type !== 'declaration_statement') continue;
        if (element.declaration.type !== 'declarator_list') continue;
        if ((element.declaration.specified_type.qualifiers?.[0] as KeywordNode)?.token !== 'uniform') continue;

        let type: string;
        if (element.declaration.specified_type.specifier.specifier.type === 'identifier')
        {
            type = element.declaration.specified_type.specifier.specifier.identifier;
        }
        else if (element.declaration.specified_type.specifier.specifier.type === 'keyword')
        {
            type = element.declaration.specified_type.specifier.specifier.token;
        }
        else if (element.declaration.specified_type.specifier.specifier.type === 'type_name')
        {
            type = element.declaration.specified_type.specifier.specifier.identifier;
        }
        else
        {
            console.warn(`未处理 activeUniforms uniform type`);
        }

        //
        let unifromName = element.declaration.declarations[0].identifier.identifier;

        // 跳过采样器，GLSL中采样器与纹理共用一个名称
        if (type.indexOf('sampler') !== -1) continue;

        //
        if (type.indexOf('texture') !== -1)
        {
            unifromName = unifromName.substring(0, unifromName.length - 'Sampler'.length);
        }

        // 处理数组
        let isArray = false;
        let size = 1;
        if (element.declaration.declarations[0].quantifier)
        {
            const expression = element.declaration.declarations[0].quantifier[0].expression;
            isArray = true;
            unifromName = `${unifromName}[0]`;
            if (expression.type === 'int_constant')
            {
                size = Number(expression.token);
            }
            else if (expression.type === 'identifier')
            {
                size = getConstValue(program, expression.identifier);
                if (!size)
                {
                    console.error(`无法解析数组长度`);
                }
                //
            }
            else
            {
                console.error(`无法解析数组长度`);
            }
        }

        options.activeUniforms.push({
            name: unifromName,
            type: type as any,
            size,
        });
    }
}

function getConstValue(program: Program, constName: string)
{
    for (let i = 0; i < program.program.length; i++)
    {
        const subProgram = program.program[i];
        if (subProgram.type === 'declaration_statement')
        {
            if (subProgram.declaration.type === 'declarator_list')
            {
                if (subProgram.declaration.declarations[0]?.identifier.identifier === constName)
                {
                    if (subProgram.declaration.declarations[0]?.initializer.type === 'int_constant')
                    {
                        const result = Number(subProgram.declaration.declarations[0]?.initializer.token);

                        return result;
                    }

                    console.error(`未处理 getConstValue ${constName}`);
                }
            }
        }
    }

    return undefined;
}
